package com.ttnet.dao.base.implemantations;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.SessionFactory;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.ttnet.dao.base.GenericDao;

/**
 * @author serhan.tuygun
 * 
 */
@Transactional(propagation = Propagation.REQUIRED, readOnly = false, value = "transactionManager")
public abstract class GenericDaoImpl<T, ID extends Serializable> implements GenericDao<T, ID> {

	protected SessionFactory sessionFactory;

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	private Class<T> persistentClass;

	public GenericDaoImpl() {
		Type type = getClass().getGenericSuperclass();
		if (type instanceof ParameterizedType) {
			ParameterizedType parameterizedType = (ParameterizedType) type;
			setPersistentClass((Class<T>) parameterizedType.getActualTypeArguments()[0]);
		} else {
			System.out.println("Not an instance of parameterized type: " + type);
		}
	}

	public Class<T> getPersistentClass() {
		return persistentClass;
	}

	public void setPersistentClass(Class<T> persistentClass) {
		this.persistentClass = persistentClass;
	}

	@Override
	public T addEntity(T entity) {
		sessionFactory.getCurrentSession().save(entity);
		return entity;
	}

	@Override
	public void removeEntityById(ID id) {
		removeEntity(findEntity(id));
	}

	@Override
	public void removeEntity(T entity) {
		sessionFactory.getCurrentSession().delete(entity);
	}

	@Override
	public void updateEntity(T entity) {
		sessionFactory.getCurrentSession().update(entity);
	}

	@Override
	public T findEntity(ID id) {
		return (T) sessionFactory.getCurrentSession().get(getPersistentClass(), id);
	}

	@Override
	public List<T> findEntities() {
		Criteria crit = sessionFactory.getCurrentSession().createCriteria(getPersistentClass());
		return crit.list();
	}

}